#include "MyLog.h"

namespace my
{
	static const size_t MAX_PRESERVED_LENGTH = 4096;

	thread_local std::vector<char> tls_log_buffer;

#if defined(_MSC_VER)
	void LogSystem::write_f(const char *name, LogLevel minimal_level, LogLevel current_level, _In_z_ _Printf_format_string_ const char *format, ...)
#else
	void LogSystem::write_f(const char *name, LogLevel minimal_level, LogLevel current_level, const char *format, ...)
#endif
	{
		if (current_level < minimal_level)
		{
			return;
		}

		va_list ap;

		va_start(ap, format);
		int length = vsnprintf(nullptr, 0, format, ap);
		va_end(ap);

		if (length <= 0)
		{
			return;
		}

		std::vector<char> &buffer = tls_log_buffer;
		buffer.resize(length + 1);
		char *text = &buffer[0];

		va_start(ap, format);
		vsnprintf(text, length + 1, format, ap);
		va_end(ap);

		write_to_output(name, current_level, text, length);

		if (length >= MAX_PRESERVED_LENGTH)
		{
			std::vector<char>().swap(buffer);
		}
	}


	const char *LogSystem::get_level_name(LogLevel level)
	{
		switch (level)
		{
		case LogLevel::Verbose:	return "VORBS";
		case LogLevel::Debug:	return "DEBUG";
		case LogLevel::Info:	return "INFOM";
		case LogLevel::Warning:	return "WARNG";
		case LogLevel::Error:	return "ERROR";
		case LogLevel::Fatal:	return "FATAL";
		default:				return "UNOWN";
		}
	}


	void LogSystem::write_to_output(const char *name, LogLevel level, const char *text, size_t text_length)
	{
		for (auto &output : m_outputs)
		{
			output->write(name, level, text, text_length);
		}
	}
}
